<template>
  <a-modal
    v-model="isModalVisible"
    :mask-closable="false"
    title="自定义拆分"
    class="split-column"
    cancel-text="取消"
    ok-text="拆分"
    @ok="onOk"
    @cancel="onCancel"
  >
    <a-row class="row">
      <a-col :span="5" class="label">
        <span style="margin-right: 4px;">拆分方式</span>
        <a-tooltip>
          <template slot="title"
            >根据字段内存在的分隔符对字段进行拆分，分隔符不包含在拆分后的字段中</template
          >
          <a-icon type="exclamation-circle" theme="filled" />
        </a-tooltip>
      </a-col>
      <a-col :span="15" :style="{ lineHeight: '30px' }">
        <span>分隔符</span>
      </a-col>
    </a-row>
    <a-row class="row">
      <a-col :span="5" class="label"> 使用分隔符 </a-col>
      <a-col :span="15" :class="{ 'has-error': hasError }">
        <a-input
          ref="inputSeparator"
          v-model="separator"
          placeholder="例如：-,."
          @change="handleSeparatorChangeDebounced"
        /><br />
        <span v-show="!validSeparator" class="error-message"
          >请输入有效的分隔符</span
        >
      </a-col>
    </a-row>
    <a-row v-if="inited && validSeparator" class="row">
      <a-col :span="5" class="label"> 拆分 </a-col>
      <a-col :span="30">
        <a-select
          default-value="1"
          :value="`${splitType}`"
          class="select"
          @change="handleSplitTypeChange"
        >
          <a-select-option value="1"> 前 </a-select-option>
          <a-select-option value="2"> 后 </a-select-option>
          <a-select-option value="3"> 全部 </a-select-option>
        </a-select>

        <a-select
          default-value="1"
          class="select"
          :value="`${splitNum}`"
          :disabled="splitType === 3"
          @change="handleSplitNumberChange"
        >
          <a-select-option v-for="item in options" :key="item" :value="item">
            {{ item }}
          </a-select-option>
        </a-select>
        字段
      </a-col>
    </a-row>
    <a-row v-if="inited && validSeparator" class="row">
      <a-col :span="5" class="label"> 拆分后的字段名 </a-col>
      <a-col :span="15">
        <div class="output-column-name">
          <span v-for="i in splitNum" :key="i" class="column-name">
            <span>{{ i }}</span>
            <a-input v-model="newColumnNames[i - 1]" />
          </span>
        </div>
      </a-col>
    </a-row>
  </a-modal>
</template>

<script lang="ts">
import { Vue, Component, Prop, Watch } from 'vue-property-decorator'
import { IColumn, IKeyValueStore } from '@/store/modules/dataview'
import { apiGetRecommendSplit, apiMaxSplit } from '@/api/data-clean'
import { StatisticsAction } from '@/util/data-selection-actions'
import { debounce } from 'lodash'

@Component
export default class SplitColumn extends Vue {
  @Prop() column!: IColumn
  @Prop() tableName!: string
  @Prop() taskId!: string
  @Prop() editData!: any
  @Prop({ default: false }) isEdit!: boolean
  @Prop({ default: '' }) parentTableName!: boolean
  @Prop({ default: [] }) columnList!: IColumn[] // 全部的列字段
  private isModalVisible: boolean = true
  private splitType: number = 1
  private splitNum: number = 1
  private maxSplitNum: number = 1
  private separator: string = ''
  private hasError: boolean = false
  private inited: boolean = false // 异步挂载，等获取到数据后，后再用v-if控制显示对应的视图
  private validSeparator: boolean = true
  private newColumnNames: string[] = []

  private handleSplitTypeChange(value: string) {
    this.splitType = +value
    if (this.splitType === 3) {
      this.splitNum = this.maxSplitNum
    }
    this.newColumnNames = [...this.autoCompleteColumnName()]
  }

  private handleSplitNumberChange(value: string) {
    this.splitNum = +value
    this.newColumnNames = [...this.autoCompleteColumnName()]
  }

  private handleSeparatorChangeDebounced = debounce(async () => {
    this.handleSeparatorChange()
  }, 300)

  private async handleSeparatorChange() {
    // 一旦用户更改了分隔符，需要重新获取当前列能拆分的最大数量
    await this.getMaxSplit()
    this.validSeparator = !(this.maxSplitNum <= 0)
    console.log(this.maxSplitNum, this.validSeparator)
    // 将已选择的分割方式与分割数量重置，否则会与上一次选择的结果混淆
    this.splitType = 1
    this.splitNum = 1
    this.newColumnNames = [...this.autoCompleteColumnName()]
  }

  private get dataSetColumnsNames() {
    const getNameColumns = this.columnList.map((item) => item.name)
    return getNameColumns
  }

  private get formatDescription() {
    let description = `分隔符${this.separator}，拆分`
    if (this.splitType === 3) {
      description += '全部'
    } else {
      description += `${this.splitType === 1 ? '前' : '后'}${
        this.splitNum
      }个字段`
    }
    return description
  }

  private checkNames() {
    const userInputNames = this.newColumnNames.slice(0, this.splitNum)
    const removeDup = new Set(userInputNames)
    if (userInputNames.length < this.splitNum) {
      this.$message.warning('请填写全部字段名')
      return false
    }
    // 用户输入的自定义列名有重复
    if (removeDup.size < userInputNames.length) {
      this.$message.warning('拆分后的字段名有重复，请检查字段名')
      return false
    }

    // 查询用户输入的列名与当前数据集中的列名是否有重复
    const found = this.dataSetColumnsNames.find((dataSetName) =>
      removeDup.has(dataSetName)
    )
    if (found !== undefined) {
      this.$message.error(`字段名${found}和已有字段重复，请修改后再提交`)
      return false
    }

    return true
  }

  async mounted() {
    if (this.column.desc && ['varchar', 'text'].includes(this.column.desc)) {
      await this.getRecommendSplit()
    }
    this.$nextTick(() => {
      // @ts-ignore
      this.$refs.inputSeparator.focus()
    })
    await this.getMaxSplit()
    if (this.separator.length === 0 || this.maxSplitNum <= 0) {
      this.validSeparator = false
    }
    this.newColumnNames = [...this.autoCompleteColumnName()]
    this.inited = true
  }

  @Watch('editData', { immediate: true, deep: true })
  private onCurrentHistory(newValue: IKeyValueStore) {
    if (!newValue || !this.isEdit) {
      return
    }
    const history = newValue.data
    if (
      history.actionType === StatisticsAction.splitColumn &&
      history.col === this.column.name
    ) {
      this.separator = history.separator
      this.splitType = history.splitType
      this.splitNum = history.splitNum
    }
  }

  // 获取推荐的分隔符
  async getRecommendSplit() {
    const response = await apiGetRecommendSplit({
      data: {
        table: this.tableName,
        type: this.column.type,
        name: this.column.name,
        taskId: this.taskId,
      },
    })
    const { separators } = response.data.result || {}
    if (separators && separators.length > 0 && !this.editData.data.separator) {
      ;[this.separator] = separators
    }
  }

  // 获取当前字段的最大可拆分数
  async getMaxSplit() {
    const response = await apiMaxSplit({
      data: {
        col: this.column.name,
        separator: this.separator,
        table: this.tableName,
      },
    })
    const maxSplit = response.data.result
    if (maxSplit) {
      this.maxSplitNum = maxSplit
    }
  }

  get options() {
    if (this.maxSplitNum <= 0) {
      return []
    }
    return new Array(this.maxSplitNum)
      .fill(0)
      .map((item: any, idx: number) => idx + 1)
  }

  private autoCompleteColumnName() {
    if (this.maxSplitNum <= 0) {
      return []
    }

    let currentSplit = 1
    if (this.splitType === 3) {
      currentSplit = this.maxSplitNum
    } else {
      currentSplit = this.splitNum
    }
    const newColumns = new Array(currentSplit)
      .fill(0)
      .map((item: any, idx: number) => idx + 1)
    return [...newColumns.map((item: number) => `${this.column.name}_${item}`)]
  }

  onOk() {
    if (!this.separator) {
      return
    }

    // 校验用户输入的列名
    if (!this.checkNames()) {
      return
    }

    this.emitSplitParams()
  }

  onCancel() {
    this.$emit('on-filter-params-change', null)
    this.$emit('config-cancel')
    this.isModalVisible = false
  }

  /**
   * 抛出去清洗动作参数
   */
  private emitSplitParams() {
    this.$emit('on-filter-params-change', {
      data: {
        action: 'SPLIT',
        col: this.column.name,
        columnName: this.column.name,
        newCol: this.newColumnNames.slice(0, this.splitNum),
        separator: this.separator,
        splitType: this.splitType,
        splitNum: this.splitNum,
        description: this.formatDescription,
        actionType: StatisticsAction.splitColumn,
      },
    })
  }
}
</script>

<style lang="less" scoped>
.split-column {
  .row {
    margin-top: 14px;
  }

  .label {
    line-height: 30px;
    margin-right: 8px;
    text-align: right;
  }

  .select {
    margin-right: 12px;
    width: 120px;
  }

  .error-message {
    color: #f5222d;
    font-size: 12px;
    line-height: 1.5;
  }

  .output-column-name {
    column-gap: 10px;
    display: flex;
    flex-wrap: wrap;

    .column-name {
      column-gap: 4px;
      display: flex;
      flex: 1;
      line-height: 30px;
      margin-bottom: 4px;
      min-width: calc(100% / 2.1);
    }
  }
}
</style>
